/*
 * This file is Copyright 2002-2006 Loyola University Chicago,
 * Department of Computer Science and the Emerging Technologies Laboratory.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License via
 *    http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.citep.web.gwt.widgets;
import java.util.ArrayList;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;


public class FaderQueue {

	protected static int RED_IDX = 0; //index for the red color in the color array
	protected static int GREEN_IDX = 1; //index for the green color in the color array
	protected static int BLUE_IDX = 2; //index for the blue color in the color array
	
	protected int steps;	//number of steps for this effect
	protected int currStep; //current step
	protected int interval; //interval in milliseconds

	protected ArrayList items;
	
	
	FaderQueue(int steps, int interval) {
		if(steps < 1)
			throw new RuntimeException("Fader: steps must be > 0");
		this.steps = steps;
	
		if(interval < 1)
			throw new RuntimeException("Fader: interval must be > 0");
		this.interval = interval;
		
		items = new ArrayList();
		
	}
	
	protected class FadeItem {
		protected Element element;
		protected String property;

		protected float dr; //red increment
		protected float dg; //green increment
		protected float db; //blue increment

		protected int [] startColor = null;
		protected int [] endColor = null;
		

		private int [] parseColor(String color) {
			if(color == null)
				throw new RuntimeException("FaderQueue.FadeItem.parseColor: Color cannot be null");
			
			if(color.charAt(0) == '#')
				color = color.substring(1);
			
			if(color.length() != 6)
				throw new RuntimeException("FaderQueue.FadeItem.parseColor: Color must be in the format #rrggbb");
			
			int colorArray[] = new int[3];
			
			for(int i = 0; i < 3; i++) {
				colorArray[i] =	Integer.parseInt(color.substring(i*2, i*2+2), 16);
				if(colorArray[i] < 0 || colorArray[i] > 255)
					throw new RuntimeException("parseColor: invalid color: " + colorArray[i] + "(" + color + ")");
			}
			
			return colorArray;
		}

		
		
		protected void init() {
			dr = (endColor[RED_IDX] - startColor[RED_IDX])/(float)steps;
			dg = (endColor[GREEN_IDX] - startColor[GREEN_IDX])/(float)steps;
			db = (endColor[BLUE_IDX] - startColor[BLUE_IDX])/(float)steps;
		}
		
		public FadeItem(Element e, String property, String startColor, String endColor) {
			this.element = e;
			this.property = property;
			this.startColor = parseColor(startColor);
			this.endColor = parseColor(endColor);
			
			init();
		}
		
		public Element getElement() {
			return element;
		}
		
		public String getProperty() {
			return property;
		}

		public void next() {
			
			String color;
			
			
			color = "#" + formatHex(Integer.toHexString((int)(startColor[RED_IDX]+dr*currStep)))
						+ formatHex(Integer.toHexString((int)(startColor[GREEN_IDX]+dg*currStep)))
						+ formatHex(Integer.toHexString((int)(startColor[BLUE_IDX]+db*currStep)));
			
			
			DOM.setStyleAttribute(element, property, color);
		}
	}
	
	void addElement(Element e, String property, String startColor, String endColor) {
		if(!startColor.equals(endColor))
			items.add(new FadeItem(e,property,startColor,endColor));
	}
	
	public int getInterval() {
		return interval;
	}
	
	public void start() {
		currStep = 0;
		startTimer(this);
	}

	protected static void startTimer(final FaderQueue fader) {
		Timer t = new Timer() {
			public void run() {
				if(!fader.next())
					cancel();
			}
		};
		
		t.scheduleRepeating(fader.getInterval());
	}
	
	protected String formatHex(String hex) {
		if(hex.length() < 2)
			return "0" + hex;
		else
			return hex;
	}
	
	public boolean next() {
		
		for(int i = 0; i < items.size(); i++)
			((FadeItem)items.get(i)).next();

		currStep++;
		
		
		return currStep < steps;
	}
	
}
